#pragma once

/*************************	Header *****************************/

#include "../numeric.h"
#include "../FunctionObjects/system.h"
#include <armadillo>
#include <functional>

#ifdef GRAPHENETOOLS_EXPORTS
#ifndef GRAPHENETOOLS_DLL_API
#define GRAPHENETOOLS_DLL_API __declspec(dllexport)
#endif
#else
#ifndef GRAPHENETOOLS_DLL_API
#define GRAPHENETOOLS_DLL_API __declspec(dllimport)
#endif
#endif

using arma::sp_cx_mat;


/*********************** Declaration ***************************/

// The Hamiltonian Functor.
//
//	This function object is used to calculate hamiltonians and the
//	like, including to date:
//
//	-	The transfer integral matrix H for a Unit (a collection 
//		of connected atoms, see the class Unit)
//
// Options:
//	The options are public variables (accessable from outside the
//	class) and are set to default value at class construction time.
//
// (System*) system;		Default:	&System::Std
//		A pointer to the used system. The system contains variables 
//		needed to construct elements (coupling strengths etc.).
//		The system defaults to a statically generated system (the
//		standard system).
//
// (double) bias;			Default:	0
//		A double containing the current bias (for bi-layered 
//		systems).
//		The bias defaults to 0 i.e no bias.
//
// (vec) k;			Default:	vec(0,0,0)
//		A double vector containing the current k-point.
//		The k defaults to vec(0,0,0) i.e the gamma point.
//
// Usage:
//	This function includes the following public operating functions.
//
//	(Hamiltonian &) operator()(int id)
//		This operator (use by simply appending () to a Hamiltonian
//		type variable) calculates the transfer integral matrix H 
//		as a sparse complex matrix (sp_cx_mat). The operator returns
//		the object it self for easy access to result.
//		The result is stored in the H result variable. The variable
//		may be retrieved immidiately after calculation i.e:
//		hamilton(id).H // Calculate and retreive result.
// 
// Example:
//	Set bias and get H matrix:
//
//		Hamiltonian hamilton; // Generate a hamilton object
//		hamilton.bias = current_bias; // Set the current bias
//		return hamilton().H; // Calculate and return result.
class GRAPHENETOOLS_DLL_API Hamiltonian
{
// Options:
public:
	// A pointer to the used system. The system contains variables 
	// needed to construct elements (coupling strengths etc.).
	System* system;
	// A double containing the current bias (for bi-layered 
	// systems).
	double bias;
	// A double vector containing the current k-point.
	vec k;
	
// Usage:

	// This operator (use by simply appending () to a Hamiltonian
	// type variable) calculates the transfer integral matrix H 
	// as a sparse complex matrix (sp_cx_mat). The operator returns
	// the object it self for easy access to result.
	arma_noinline Hamiltonian &operator()(int id);

// Results:

	// The transfer integral matrix for a Unit. Use 
	// operator()(int id) to set.
	sp_cx_mat H;
	
// Constructor
	Hamiltonian();
protected:
	
	complex getHamiltonElement(const Bond &bond);
};

